from datetime import datetime
from os import write
import os
import random
import shutil
import requests
from bs4 import BeautifulSoup
from soupsieve import match
import yaml
import pandas as pd
import re
from openpyxl import Workbook, load_workbook
from openpyxl.styles import Font, Alignment
import subprocess

with open('config.yml', 'r', encoding='utf-8') as f:
    config = yaml.safe_load(f)

class UpdateOaDoc:
    def __init__(self, cookie_oa, pageNum, isAuto):
        self.cookie_oa = cookie_oa
        self.pageNum = pageNum
        self.isAuto = isAuto
        self.file_path = config['home_dir'] + '/收文本.xlsx'
        
    def doUpdate(self):
        # 让用户可选读取的文件数目
        if '-' in self.pageNum:
            parts = self.pageNum.split('-')  # 按 '-' 分割字符串
            num1 = int(parts[0])  # 第一个部分 '1' 转为整数
            num2 = int(parts[1])  # 第二个部分 '8' 转为整数
            # 获取目录内容
        else:
            num1 = int(self.pageNum)
            num2 = num1
        matches = self.getFileNum(num1, num2)
        if not matches:
            print('没有找到文件编号或未更新cookie')
            return False
        return self.writeInExcel(matches)
    
    def writeInExcel(self, matches):
        
        # 如果当前文件夹中有文件名存在‘临时文件’，则删除
        for file in os.listdir(config['code_dir']):
            if '临时文件' in file:
                # 而且后缀名为.xlsx
                if file.endswith('.xlsx'):
                    # 去到指定的目录
                    os.chdir(config['code_dir'])
                    os.remove(file)
        
        if self.isAuto:
            # 读取文档
            wb = load_workbook(self.file_path)
            ws = wb.active
            last_row = ws.max_row
            url = ws.cell(row=last_row, column=8).value
            if url:
                # 字符串的后面四位数字
                last_file_num = int(url[-4:])
                # 找到match中大于last_file_num的
                for match in matches:
                    if int(match) == last_file_num:
                        # 修改matches
                        matches = matches[matches.index(match)+1:]
        else:
            # 检查是否存在OA收文本.xlsx
            if os.path.exists(config['code_dir'] + '/OA收文本.xlsx'):
                os.remove(config['code_dir'] + '/OA收文本.xlsx')
            # 新建一个Excel文件
            wb = Workbook()
            ws = wb.active
            ws.title = 'OA'
            
        file_data = self.getContent(matches)
            
        row_num = ws.max_row
        # 设置各列宽度（单位：字符宽度）
        ws.column_dimensions['B'].width = 10.0  # 第2列
        ws.column_dimensions['C'].width = 15.0  # 第3列
        ws.column_dimensions['D'].width = 70.0  # 第4列
        ws.column_dimensions['G'].width = 15.0  # 第7列
        ws.column_dimensions['H'].width = 70.0  # 第8列
        
        # === 定义对齐方式（垂直居中 + 自动换行） ===
        alignment = Alignment(
            vertical='center',    # 垂直居中
            horizontal='left',    # 水平左对齐（可选：'center', 'right'）
            wrapText=True         # 自动换行
        )
        
        # 定义字体样式（12号方正小标宋简体）
        header_font = Font(
            name='方正小标宋简体',  # 确保系统已安装该字体
            size=12,
            bold=False  # 不加粗
        )
        if row_num == 1:
            ws.cell(row=row_num, column=1, value='收文号').alignment = alignment
            ws.cell(row=row_num, column=2, value='日期').alignment = alignment
            ws.cell(row=row_num, column=3, value='来文单位').alignment = alignment
            ws.cell(row=row_num, column=4, value='标题').alignment = alignment
            ws.cell(row=row_num, column=5, value='收文处理').alignment = alignment
            ws.cell(row=row_num, column=6, value='限办日期').alignment = alignment
            ws.cell(row=row_num, column=7, value='责任科室/人员').alignment = alignment
            ws.cell(row=row_num, column=8, value='直达链接（需要先登录OA）').alignment = alignment
            # 应用字体样式到表头
            for col in range(1, 9):
                ws.cell(row=row_num, column=col).font = header_font
            # 设置行高为25
            ws.row_dimensions[row_num].height = 25
            # 冻结窗格（冻结到表头行下方，即B2单元格上方）
            ws.freeze_panes = 'A2'
        
        # 2. 写入数据
        for data in file_data:
            row_num += 1
            ws.cell(row=row_num, column=2, value=data[0]).alignment = alignment
            ws.cell(row=row_num, column=3, value=data[1]).alignment = alignment
            ws.cell(row=row_num, column=4, value=data[2]).alignment = alignment
            ws.cell(row=row_num, column=7, value=data[3]).alignment = alignment
            link_cell = ws.cell(row=row_num, column=8, value=data[4])
            link_cell.hyperlink = data[4]  # 设置超链接
            link_cell.font = Font(color="0000FF", underline="single")  # 蓝色 + 单下划线
            link_cell.alignment = alignment  # 应用垂直居中 + 自动换行

        # 写入更新时间
        # 检查是否存在指定的工作表
        if '运行日志' in wb.sheetnames:
            # 获取指定的活动工作表
            ws = wb['运行日志']
            # 在第二列第一行写入当前时间
            ws.cell(row=1, column=2, value=datetime.now().strftime("%Y-%m-%d %H:%M:%S"))

        # 3. 保存 Excel 文件
        if self.isAuto:
            wb.save(self.file_path)
        else:
            # 获取一个四位数的随机数
            random_num = random.randint(1000, 9999)
            wb.save(config['code_dir'] + f"/OA收文本（临时文件{random_num}）.xlsx")
            try:
                subprocess.run(["et", config['code_dir'] + f"/OA收文本（临时文件{random_num}）.xlsx"], check=False)
            except FileNotFoundError:
                print("错误：WPS 未安装或不在 PATH 环境变量中")
            except subprocess.CalledProcessError as e:
                print(f"错误：WPS 打开失败（返回码 {e.returncode}）")
        
        # 4. 关闭 Excel 文件
        wb.close()
        
        return True

    def getFileNum(self, pageNum1, pageNum2):
        matches = []
        for pageNum in range(pageNum1, pageNum2+1):
            getListUrl = config['oa_url']['list_url'] + str(pageNum)
            config['oa_headers']['Cookie'] = self.cookie_oa
            response = requests.post(getListUrl, headers=config['oa_headers'])
            content = response.text
            # print(content)
            # 从html找出value
            soup = BeautifulSoup(content, 'html.parser')
            for input_tag in soup.find_all('input', {'name': 'ids[]'}):
                val = input_tag.get('value')
                matches.append(val)
        # 排序 从小到大
        matches.sort(key=lambda x: int(x))
        return matches

    def getContent(self, matches):
        # 删除error目录下的所有文件再创建
        shutil.rmtree(config['code_dir'] + '/error')
        os.makedirs(config['code_dir'] + '/error')
        
        
        file_data = []
        
        # 从match的第一个数字遍历到最后一个数字
        first_file_num = int(matches[0])
        last_file_num = int(matches[-1])
        for file_num in range(first_file_num, last_file_num+1):
            try:
                # start 获取详情
                get_det_url = config['oa_url']['detail_url'] + str(file_num)
                response = requests.get(get_det_url, headers=config['oa_headers'])
                if response.status_code != 200:
                    print(f'获取详情失败，文件编号：{file_num}')
                    # 写入文件
                    with open(f'error/{file_num}.html', 'a', encoding='utf-8') as f:
                        f.write(response.text)
                    continue
                # soup = BeautifulSoup(response.text, 'html.parser') 

                pattern_fromDep = r'<td width="76" >来文单位</td><td width="508" >(.*?)</td>'
                pattern_title = r'<td width="76" >标&nbsp;&nbsp;题</td><td width="1091"  colspan="3">(.*?)</td>'
                pattern_date = r'<td width="76" >收文日期</td><td width="508" >(.*?)</td>'
                pattern_nb = r'<td width="1138" class="td_box" id="hshenheyj"  colspan="3"><p><p>(.*?)</p>'
                
                match_fromDep = re.search(pattern_fromDep, response.text)
                match_title = re.search(pattern_title, response.text)
                match_date = re.search(pattern_date, response.text)
                match_nb = re.search(pattern_nb, response.text)
                
                if match_nb is None:
                    pattern_nb = r'<td width="1138" class="td_box" id="hshenheyj"  colspan="3"><p><p>(.*?)<br />'
                    match_nb = re.search(pattern_nb, response.text)
                
                date = match_date.group(1) if match_date else None
                # 解析日期
                date_obj = datetime.strptime(date, "%Y年%m月%d日")
                # 格式化为新格式
                new_date = date_obj.strftime("%Y/%-m/%-d")
                fromDep = match_fromDep.group(1) if match_fromDep else None
                title = match_title.group(1) if match_title else None
                nb = match_nb.group(1) if match_nb else None
                
                print(new_date, fromDep, title)
                
                # 提取字符串
                departments = ['请办公室','局办公室', '高新科', '产学研科', '法规科', '社农科', '专家科','成果科','情报所', '机关党委', '地震监测中心',
                            '送各业务科室','拟请各科室','拟请各业务科室','局工会','局务会','局妇委会','局办公室（财务）','局办公室（人事）']
                nb = nb or []
                dep = [d for d in departments if d in nb] # ***
                dep_to_string = '、'.join(dep).replace("拟请", "").replace("送", "").replace("局办公室、局办公室", "局办公室").replace("请办公室", "局办公室")

                if '已核' not in response.text:
                    string_array = [new_date, fromDep, title, dep_to_string + "（未核）", get_det_url, ]
                else:
                    string_array = [new_date, fromDep, title, dep_to_string, get_det_url]
                file_data.append(string_array)
            except Exception as e:
                print(f'获取详情失败，文件编号：{file_num}，错误信息：{e}')
                # 写入文件
                with open(f'error/{file_num}.html', 'a', encoding='utf-8') as f:
                    f.write(response.text)
                continue
        
        return file_data